import { createApp } from 'vue'
import App from 'src/App.vue'
const Vue = createApp(App)
Vue.mount('#app');
import { ElMessageBox, ElMessage } from 'element-plus'

import moment from 'moment'
import { designerStore } from 'src/stores/designerTool/designerTool'
// import store from '@/store'
import { isObject, isArray, isString } from 'src/utils/designerTool/validate'
// import DagGraph from 'src/pages/designerTool/canvas/DagEdit/graph'

let store = designerStore()
// 消息弹出
export function layer_message(message, type, duration = 3000, dangerouslyUseHTMLString = false) {
  if (!message) return
  ElMessage({
    showClose: true,
    duration,
    message,
    dangerouslyUseHTMLString,
    type: type || 'error'
  })
}

// 页面表格操作确认弹窗,主要可以在里面做loading
// msgType 1,模板模式,2.文字自定义
export function msgboxHandle(config, msgType = 1) {
  const { type, key, name, api, data, successHandle, title, message, errorHandle, successMessage } = config
  ElMessageBox({
    title: msgType === 1 ? `${type}${key}数据` : title,
    message: msgType === 1 ? `确定要${type}名称为 ${name} 的${key}吗？` : message,
    dangerouslyUseHTMLString: msgType !== 1,
    showCancelButton: true,
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: type === '删除' ? 'error' : 'warning',
    beforeClose: (action, instance, done) => {
      function close() {
        instance.confirmButtonLoading = false
        instance.confirmButtonText = '确定'
      }
      if (action === 'confirm') {
        instance.confirmButtonLoading = true
        instance.confirmButtonText = `${type}中...`
        try {
          Vue.prototype.$api[api](data).then((res) => {
            if (successHandle) {
              successHandle(res)
            }
            done()
            layer_message(successMessage || `${type}成功`, 'success')
          }, res => {
            if (errorHandle) {
              errorHandle(res, done)
            } else {
              layer_message(res.result)
            }
          }).finally(() => {
            close()
          })
        } catch (err) {
          layer_message(err.toString())
          close()
        }
      } else {
        done()
      }
    }
  }).then(action => {
    console.log(action)
  }).catch(error => {
    console.log(error)
  })
}

export function bytesToSize(bytes) {
  bytes = parseInt(bytes)
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']
  if (bytes === 0) return '0 Byte'
  const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)))
  return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i]
}

export function download(url, fileName) {
  const $a = document.createElement('a')
  $a.setAttribute('href', url)
  if (fileName) {
    $a.setAttribute('download', fileName)
  }
  $a.click()// 自执行点击事件
}

export function getFileUUID() {
  return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
    var r = Math.random() * 16 | 0
    var v = c === 'x' ? r : (r & 0x3 | 0x8)
    return v.toString(16)
  })
}

export function getFileUUIDShort() {
  return 'xxxxxxxx'.replace(/[xy]/g, function (c) {
    const r = Math.random() * 16 | 0
    const v = c === 'x' ? r : (r & 0x3 | 0x8)
    return v.toString(16)
  })
}

export function formatDate(value, format = 'YYYY-MM-DD HH:mm:ss') {
  if (value) {
    try {
      let intTime = value
      if ((intTime + '').length === 10) {
        intTime = parseInt(intTime * 1000)
      }
      if (typeof intTime === 'string') {
        intTime = parseInt(value)
      }
      return moment(intTime).format(format)
    } catch (e) {
      return ''
    }
  } else {
    return ''
  }
}

function numHandle(num) {
  if (num === 0) {
    return '00'
  } else if (num < 10) {
    return '0' + num
  }
  return num
}

export function timerDateHandle(type, time, suffix = '以前', expire = '刚刚') {
  if (!time) {
    return ''
  }
  if ((time + '').length === 13) {
    time = parseInt((Date.now() - time) / 1000)
  } else if ((time + '').length === 10) {
    time = parseInt((Date.now() - time * 1000) / 1000)
  }
  const year = Math.floor(time / (86400 * 365))
  const month = Math.floor(time / (86400 * 30))
  const day = Math.floor(time / 86400)
  const hour = parseInt((time % (86400)) / (3600))
  const minute = parseInt((time % (3600)) / (60))
  const second = parseInt(time % (60))
  if (type === 1) {
    if (day) {
      return numHandle(day) + ' 天 ' + numHandle(hour) + ' 小时'
    } else if (hour) {
      return numHandle(hour) + ' 小时 ' + numHandle(minute) + ' 分钟'
    } else {
      return numHandle(minute) + ' 分钟 ' + numHandle(second) + ' 秒'
    }
  } else {
    if (year > 0) return year + ' 年' + suffix
    if (month > 0) return month + ' 月' + suffix
    if (day > 7) return Math.floor(day / 7) + ' 周' + suffix
    if (day > 0) return day + ' 天' + suffix
    if (hour > 0) return hour + '小时' + suffix
    if (minute > 0) return minute + '分钟' + suffix
    if (second > 5) return second + '秒' + suffix
    return expire
  }
}

export function secondToTime(flow_run_time) {
  let time = 0
  if (flow_run_time) {
    if (flow_run_time.start_time) {
      if (flow_run_time.end_time) {
        time = flow_run_time.end_time - flow_run_time.start_time
      } else {
        time = (parseInt(new Date().getTime() / 1000)) - flow_run_time.start_time
      }
    }
  }
  if (!time) return ''
  let minute = 0// 分
  let hour = 0// 小时
  let day = 0 // 天
  const result = []
  if (time >= 60) {
    minute = parseInt(time / 60)
    time = parseInt(time % 60)
    if (minute >= 60) {
      hour = parseInt(minute / 60)
      minute = parseInt(minute % 60)
      if (hour >= 24) {
        day = parseInt(hour / 24)
        hour = parseInt(hour % 24)
        result.push(numHandle(day) + '天')
      }
      result.push(numHandle(hour) + '小时')
    }
    result.push(numHandle(minute) + '分')
  }
  result.push(numHandle(time) + '秒')
  return result.join('')
}

// 获取一个字符串在页面具体占用的宽高
export function getTextWidth(str, element, style) {
  const spanDom = document.createElement(element)
  spanDom.style.fontSize = '14px'
  spanDom.style.fontFamily = 'Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,微软雅黑,Arial,sans-serif;'
  for (const s in style) {
    spanDom.style[s] = style[s]
  }
  spanDom.innerHTML = str
  document.body.append(spanDom)
  const sizeD = spanDom.getBoundingClientRect()
  spanDom.remove()
  return sizeD
}

// base64转blob
export const base64ToBlob = function (base64Data) {
  const arr = base64Data.split(',')
  const fileType = arr[0].match(/:(.*?);/)[1]
  const bstr = atob(arr[1])
  let l = bstr.length
  const u8Arr = new Uint8Array(l)

  while (l--) {
    u8Arr[l] = bstr.charCodeAt(l)
  }
  return new Blob([u8Arr], {
    type: fileType
  })
}

// blob转file
export const blobToFile = function (newBlob, fileName) {
  newBlob.lastModifiedDate = new Date()
  newBlob.name = fileName
  return newBlob
}

export function go_Contents(_this, path, query = null) {
  sessionStorage.setItem(_this.$route.path, JSON.stringify({
    d: _this.formQuery,
    l: _this.listQuery,
    o: _this.otherData
  }))
  const url = { path: '' }
  if (store.getters.routeName === 'modelFlow') {
    url.path += `/modelFlow/${store.getters.flowId}`
  }
  url.path += path
  if (query) {
    url['query'] = query
  }
  _this.$router.push(url)
}

// 拷贝对象
export function CopyObject(newObj, sourceObj) {
  for (const key in newObj) {
    if (sourceObj[key] !== undefined) {
      newObj[key] = sourceObj[key]
    }
  }
  return newObj
}

export function copyText(text) {
  const oInput = document.createElement('textarea')
  oInput.value = text
  document.body.appendChild(oInput)
  oInput.select()
  document.execCommand('Copy')
  oInput.className = 'oInput'
  oInput.style.display = 'none'
  layer_message('复制成功', 'success')
}

export function urlIdHandle(urlOriginal) {
  let url = urlOriginal
  const idMapping = {
    ':flowId': store.getters.flowId
  }
  const keyList = Object.keys(idMapping)
  for (let i = 0; i < keyList.length; i++) {
    if (url.indexOf(keyList[i]) !== -1) {
      if (idMapping[keyList[i]]) {
        url = url.replace(keyList[i], idMapping[keyList[i]])
      } else {
        url = ''
        break
      }
    }
  }
  return url
}

// 表格组合id组装
export function idHandle(id, prefix = '') {
  if (id && id.length > 8) {
    return prefix + id.substring(0, 8)
  }
  return id
}

export function ObjectToSelectArray(object) {
  const array = []
  for (const key in object) {
    array.push({
      label: object[key],
      value: key
    })
  }
  return array
}

export function regularText(value) {
  return /^[a-zA-Z0-9\u4e00-\u9fa5]+[a-zA-Z0-9\u4e00-\u9fa5_-]+$/.test(value)
}

export function regularTextValidator(key = '名称', min = 2, max = 20, required = true, validator = true, pattern) {
  const regular = []
  if (required) {
    regular.push({ required: true, message: `请输入${key}`, trigger: ['blur', 'change'] })
  }
  if (min && max) {
    regular.push({ min, max, message: `长度在 ${min} 到 ${max} 个字符`, trigger: ['blur', 'change'] })
  } else if (min === 0 && max) {
    regular.push({ max, message: `最大长度在 ${max} 个字符`, trigger: ['blur', 'change'] })
  } else if (min) {
    regular.push({ min, message: `最小长度在 ${max} 个字符`, trigger: ['blur', 'change'] })
  }
  if (validator) {
    regular.push({
      validator: (rule, value, callback) => {
        if (value || required) {
          if (regularText(value)) {
            callback()
          } else {
            callback(new Error(`只允许输入字母、数字、汉字、下划线'_'和中划线'-'`))
          }
        } else {
          callback()
        }
      }, trigger: ['blur', 'change']
    })
  }
  if (pattern) {
    regular.push(pattern)
  }
  return regular
}

export function operatorValidatorForm(type, message) {
  let defaultMessage = ''
  switch (type) {
    case 'string':
      defaultMessage = '请输入参数'
      break
    case 'array':
    case 'object':
      defaultMessage = '请选择一个参数'
      break
    default:
  }
  return [
    {
      validator: (rule, value, callback) => {
        if (operatorValidator(type, value)) {
          callback(new Error(message || defaultMessage))
        } else {
          callback()
        }
      }, trigger: 'blur'
    }
  ]
}

export function operatorValidator(type, value) {
  if (value === null || value === undefined) return true
  switch (type) {
    case 'string':
      return value === ''
    case 'array':
      return !Array.isArray(value) || value.length === 0
    case 'object':
      return !isObject(value) || Object.keys(value).length === 0
    default:
  }
}

export function operatorConfigHandle(row, operatorConfig) {
  if (row.configs) {
    for (const key in row.configs) {
      const rowNode = row.configs[key]
      rowNode.results.forEach(sectionRow => {
        console.log(sectionRow)
        sectionRow.results.forEach(({ id, ui_type_code, is_required, value_type_code, ui_config }) => {
          operatorConfig[id] = {
            ui_type_code, is_required, value_type_code, ui_config
          }
        })
      })
    }
  }
}

export function algoNodeValidate(node) {
  let errorType = ''
  const data = node.getData()
  // if (data.configs && isObject(data.configs)) {
  //   for (const key in data.configs) {
  //     data.configs[key].forEach(row => {
  //       const config = store.getters.operatorConfig[row.id]
  //       if (row.id && config && config.is_required) {
  //         let validatorType = ''
  //         switch (config.ui_type_code) {
  //           case 'input':
  //           case 'textarea':
  //           case 'radio':
  //             validatorType = 'string'
  //             break
  //           case 'checkbox':
  //             validatorType = 'array'
  //             break
  //           case 'select':
  //             if (config.ui_config.multiple) {
  //               validatorType = 'array'
  //             } else {
  //               validatorType = 'string'
  //             }
  //             break
  //           case 'uploadFile':
  //             validatorType = 'string'
  //             break
  //           case 'dynamicParameter':
  //           case 'conditionScreen':
  //           case 'conditionUnitScreen':
  //           case 'sortScreen':
  //           case 'arraySection':
  //           case 'expression': {
  //             validatorType = 'array'
  //             break
  //           }
  //           default:
  //         }
  //         if (validatorType && operatorValidator(validatorType, row.value)) {
  //           errorType = 'form'
  //         }
  //       }
  //     })
  //   }
  // }
  if (!errorType) {
    const nodeConfig = store.categoriesSubset[data.id]
    // if (nodeConfig.inputs && isArray(nodeConfig.inputs) && nodeConfig.inputs.length) {
    //   const inputIds = nodeConfig.inputs.map(row => row.id + '')
    //   const incomingEdges = DagGraph.graph.getIncomingEdges(node.id)
    //   let incomingPortIds = []
    //   if (incomingEdges && incomingEdges.length) {
    //     incomingPortIds = incomingEdges.map(row => row.getTargetPortId())
    //     incomingPortIds = Array.from(new Set(incomingPortIds))
    //   }
    //   if (inputIds.length !== incomingPortIds.length) {
    //     errorType = 'connect'
    //   }
    // }
  }
  return errorType
}

export function has_permission() {
  return true
}

export function logMessageHandle(text) {
  let messages = []
  if (text[2].includes('\n')) {
    const textSplice = text[2].split('\n')
    textSplice.forEach((textRow, index) => {
      if (index === 0) {
        messages.push(`${text[0]} ${text[1]} ${textRow}`)
      } else {
        messages.push(textRow)
      }
    })
  } else {
    messages = [`${text[0]} ${text[1]} ${text[2]}`]
  }
  return messages
}

export function descriptionHandle(desc) {
  let description = ''
  if (isArray(desc) && desc.length) {
    description = desc.join('<br/>')
  } else if (isString(desc)) {
    description = desc
  }
  return description
}

export function generateRoutes(projectRoutes) {
  function childrenAddParentUrl(secondLevel, path) {
    if (secondLevel.children && secondLevel.children instanceof Array && secondLevel.children.length > 0) {
      secondLevel.children.forEach(row => {
        row.meta['parentUrl'] = path
        childrenAddParentUrl(row, path)
      })
    }
  }
  // 整理目录
  function childrenHandle(routes) {
    if (routes.path === '/modelFlow/:flowId') {
      routes.children.forEach(secondLevel => {
        if (secondLevel.children && Array.isArray(secondLevel.children) && secondLevel.children.length) {
          secondLevel.children.forEach(thirdLevel => {
            childrenAddParentUrl(thirdLevel, routes.path + '/' + secondLevel.path + '/' + thirdLevel.path)
          })
        }
      })
    }
    let childrenRoutes = []
    function CollationCatalog(data, path = '') {
      data.forEach((val, index) => {
        val.path = path + val.path
        if (val.children instanceof Array && val.children.length > 0) {
          CollationCatalog(val.children, val.path + '/')
        }
        delete val.children
        if (val.component) {
          val.component = loadView(val.component)
          childrenRoutes.push(val)
        }
      })
    }
    // routes.component = (resolve) => require([`@/layout/projecLayout.vue`], resolve)
    CollationCatalog(routes.children)
    routes.children = childrenRoutes
    childrenRoutes = []
  }
  const projectRoutesJson = JSON.parse(JSON.stringify(projectRoutes))
  childrenHandle(projectRoutesJson)
  return projectRoutesJson
}

// export const loadView = (view) => { // 路由懒加载
//   return (resolve) => require([`@/views/${view}`], resolve)
// }

export function setItemData(_this) {
  sessionStorage.setItem(_this.$route.path, JSON.stringify({
    d: _this.formQuery,
    l: _this.listQuery,
    o: _this.otherData
  }))
}

// 保留两位小数
// 功能：将浮点数四舍五入，取小数点后2位
export function toDecimal(x) {
  var f = parseFloat(x)
  if (isNaN(f)) {
    return
  }
  f = Math.round(x * 100) / 100
  return f
}

export async function asyncPool(array, iteratorFn, termination = () => false, poolLimit = 10) {
  const ret = [] // 存储所有的异步任务
  const executing = [] // 存储正在执行的异步任务
  for (let i = 0; i < array; i++) {
    if (termination()) {
      break
    }
    // 调用iteratorFn函数创建异步任务
    const p = Promise.resolve().then(() => iteratorFn(i))
    ret.push(p) // 保存新的异步任务

    // 当poolLimit值小于或等于总任务个数时，进行并发控制
    if (poolLimit <= array) {
      // 当任务完成后，从正在执行的任务数组中移除已完成的任务
      const e = p.then(() => executing.splice(executing.indexOf(e), 1))
      executing.push(e) // 保存正在执行的异步任务
      if (executing.length >= poolLimit) {
        await Promise.race(executing) // 等待较快的任务执行完成
      }
    }
  }
  return Promise.all(ret)
}

export function getFlowHost() {
  return window.location.host
}
// 实验工作流状态
export function operatorRunState(stateStr){
  switch (stateStr) {
    case 'success':
      return 'success'
    case 'failed':
      return 'danger'
    case 'pending':
      return 'pending'
    case 'running':
      return ''
  }
}

export function stateText(stateStr){
  switch (stateStr) {
    case 'success':
      return '成功'
    case 'danger':
      return '失败'
    case 'pending':
      return '等待'
    case '':
      return '运行中'
  }
}
